export const DrawPosterTypeEnum = {
  // 图文
  image: 0,
  // 纯文字
  text: 1,
};

class PosterDraw {
  ctx = null;
  canvas = null;
  options = {};
  constructor(ctx, options = {}) {
    if (ctx == null) {
      throw new Error("ctx params is required");
    }
    const defaultOptions = {
      scale: 3,
      drawType: DrawPosterTypeEnum.image,
      qrcodeUrl: "https://star.top237.top",
    };
    options = { ...defaultOptions, ...options };
    this.validateOptions(options);
    const scale = options.scale;
    this.ctx = ctx;
    this.canvas = ctx.canvas;
    // this.canvas.height = window.innerHeight * 40
    // this.canvas.width = window.innerWidth * this.scale

    let styles = {
      fontSize: 20 * scale,
      fontFamily: "PingFang SC", //"PingFang SC", "Microsoft YaHei"
      color: "#656565",
      padding: 24 * scale,
      paddingTop: 24 * scale,
      paddingLeft: 24 * scale,
      paddingRight: 24 * scale,
      paddingBottom: 24 * scale,
      backgroundColor: "#FFFFFF",
      maxWidth: 680 * scale,
      textBoxPadding: 20 * scale,
      letterSpacing: 4 * scale,
      lineSpacing: 16 * scale,
    };
    if (options.styles) {
      styles = { ...styles, ...options.styles };
    }
    // styles = {...styles,...this.handlePadding(styles.padding, scale)}
    // styles = {...styles,textBoxPadding:this.handlePadding(styles.textBoxPadding, scale)}
    options.styles = styles;
    this.ctx.fillStyle = styles.backgroundColor;
    this.options = options;
    this.changeDrawType(options.drawType, false);
  }

  /**
   * 验证参数
   */
  validateOptions(options) {
    const keys = Object.keys(options);
    const requiredKeys = ["lyric", "title"];
    for (let i = 0; i < requiredKeys.length; i++) {
      if (!keys.includes(requiredKeys[i])) {
        throw new Error(`${requiredKeys[i]} is options required`);
      }
    }
    if (options.drawType === DrawPosterTypeEnum.image) {
      if (!keys.includes("imgUrl")) {
        throw new Error("imgUrl is required if drawType is equal to 0");
      }
    }
  }
  /**
   * 变化绘制海报类型
   * @param {*} type
   */
  changeDrawType(type, isInit = false) {
    if (type === null) {
      throw new Error("type is required");
    }

    if (this.options.drawType === type && isInit) {
      return;
    }
    console.log("绘制派出");
    this.options.drawType = type;
    switch (type) {
      case DrawPosterTypeEnum.image:
        drawPosterType0(this.ctx, this.options);
        break;
      case DrawPosterTypeEnum.text:
        drawPosterTypeText(this.ctx, this.options);
        break;
    }
  }

  /**
   * 处理padding值
   */

  handlePadding(padding) {
    const styles = {};
    if (padding) {
      if (typeof padding === "number") {
        styles.paddingTop = padding;
        styles.paddingBottom = padding;
        styles.paddingLeft = padding;
        styles.paddingRight = padding;
      }
      if (Array.isArray(padding)) {
        if (padding.length === 2) {
          const [block, inline] = padding;
          styles.paddingTop = block;
          styles.paddingBottom = block;
          styles.paddingLeft = inline;
          styles.paddingRight = inline;
        }
        if (padding.length === 4) {
          const [top, right, bottom, left] = padding;
          styles.paddingTop = top;
          styles.paddingBottom = right;
          styles.paddingLeft = bottom;
          styles.paddingRight = left;
        }
      }
    }
    return styles;
  }

  /**
   * canvas转bole链接
   */

  toDataURL() {
    var imgsrc = this.canvas.toDataURL();
    return imgsrc;
  }
}

export default function draw(ctx, options = {}) {
  const posterDraw = new PosterDraw(ctx, options);
  return posterDraw;
}

/**
 * 绘制图文海报
 * @param {*} ctx
 * @param {*} options
 */
async function drawPosterType0(ctx, options = {}) {
  // 画笔在画布上的位置
  let drawX = 0;
  let drawY = 0;
  // 放大倍数
  const scale = options.scale;
  const canvas = ctx.canvas;
  canvas.height = window.innerHeight * 40;
  canvas.width = window.innerWidth * scale;
  let styles = options.styles;
  ctx.fillStyle = styles.backgroundColor;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  if (options.imgUrl) {
    try {
      const img = await loadImage(options.imgUrl);
      const x = styles.padding + drawY;
      const y = styles.padding;
      const width = canvas.width - styles.padding * 2;
      const height = canvas.width - styles.padding * 2;
      ctx.drawImage(img, x, y, width, height);
      drawY += height;
    } catch (error) {
      throw new Error("加载图片失败->", error);
    }
  }
  // 绘制歌词
  if (options.lyric) {
    const point = drawText(ctx, options.lyric, styles, drawX, drawY);
    drawY = point.drawY;
  }
  drawX = 0;
  // 绘制标题
  if (options.title) {
    drawX += styles.textBoxPadding + 60 * scale;
    // 第一条路径
    ctx.beginPath();
    ctx.strokeStyle = styles.color;
    ctx.lineWidth = 1;
    ctx.moveTo(drawX, drawY);
    drawX += 80 * scale;
    ctx.lineTo(drawX, drawY);
    ctx.stroke();
    ctx.fillStyle = styles.color;
    ctx.font = `${styles.fontSize}px ${styles.fontFamily}`;
    // drawX = styles.textBoxPadding
    drawY += styles.fontSize / 2.8;
    const point = drawText(ctx, options.title, styles, drawX, drawY, { offsetX: drawX + 20, display: "inline" });
    drawY = point.drawY;
  }
  drawY += styles.padding;
  try {
    // eslint-disable-next-line
    const point = await drawBottom(
      ctx,
      { ...options, styles: { ...styles, padding: options.styles.textBoxPadding + options.styles.padding } },
      drawX,
      drawY
    );
    // eslint-disable-next-line
    drawY = point.drawY + styles.padding;
  } catch (error) {
    // eslint-disable-next-line
    console.log("error-->", error);
  }

  console.log(drawY);
  // 结束
  let canvasData = ctx.getImageData(0, 0, canvas.width, Math.ceil(drawY));
  canvas.height = Math.ceil(drawY);
  ctx.clearRect(0, 0, canvas.width, Math.ceil(drawY));
  ctx.putImageData(canvasData, 0, 0);
  drawSuccessEvent(options);
}

/**
 * 绘制纯文字海报
 * @param {*} ctx
 * @param {*} options
 */
async function drawPosterTypeText(ctx, options = {}) {
  console.log("绘制纯文字海报");
  // 画笔在画布上的位置
  let drawX = 0;
  let drawY = 0;
  // 放大倍数
  const scale = options.scale;
  const canvas = ctx.canvas;
  canvas.height = window.innerHeight * 40;
  canvas.width = window.innerWidth * scale;
  // ctx.clearRect(0,0,canvas.width,canvas.height)
  let styles = options.styles;
  ctx.fillStyle = styles.backgroundColor;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  drawX = 0;
  // 绘制歌词
  if (options.lyric) {
    const point = drawText(ctx, options.lyric, styles, drawX, drawY);
    drawY = point.drawY;
  }
  drawX = 0;
  // 绘制标题
  if (options.title) {
    drawX += styles.textBoxPadding + 60 * scale;
    // 第一条路径
    ctx.beginPath();
    ctx.strokeStyle = styles.color;
    ctx.lineWidth = 1;
    ctx.moveTo(drawX, drawY);
    drawX += 80 * scale;
    ctx.lineTo(drawX, drawY);
    ctx.stroke();
    ctx.fillStyle = styles.color;
    ctx.font = `${styles.fontSize}px ${styles.fontFamily}`;
    drawY += styles.fontSize / 2.8;
    const point = drawText(ctx, options.title, styles, drawX, drawY, { offsetX: drawX + 30, display: "inline" });
    drawY = point.drawY;
  }

  // eslint-disable-next-line
  let tmpHeight = drawY;

  // 绘制边框
  drawY = styles.padding;
  drawX = styles.padding;
  ctx.beginPath();
  ctx.strokeStyle = "#E4E4E4";
  ctx.lineWidth = 4;
  ctx.moveTo(drawX, drawY);
  drawX += canvas.width - styles.padding * 2;
  ctx.lineTo(drawX, drawY);
  drawY += tmpHeight - styles.padding * 2 + 40;
  ctx.lineTo(drawX, drawY);
  drawX -= canvas.width - styles.padding * 2;
  ctx.lineTo(drawX, drawY);
  drawY = styles.padding;
  drawX = styles.padding;
  ctx.lineTo(drawX, drawY);
  ctx.stroke();

  //绘制分号
  // const fFontSize = 136
  // drawX = styles.padding - (fFontSize / 2)
  // drawY = styles.padding + 60
  // ctx.fillStyle = styles.backgroundColor
  // ctx.fillRect(drawX, drawY, fFontSize, 70)
  // ctx.fillStyle = '#E4E4E4'
  // ctx.font = `${fFontSize}px serif`;

  // ctx.fillText('“', drawX - 20 , drawY += fFontSize)

  // drawX = canvas.width - styles.padding - (fFontSize / 2) + 18
  // drawY = tmpHeight - styles.padding - fFontSize + 40
  // ctx.fillStyle = styles.backgroundColor
  // ctx.fillRect(drawX, drawY + 20, fFontSize, 60)
  // ctx.fillStyle = '#E4E4E4'
  // ctx.fillText('”', drawX , drawY + fFontSize)

  // tmpHeight += styles.padding
  drawY = tmpHeight;
  try {
    const point = await drawBottom(ctx, options, drawX, drawY);
    drawY = point.drawY + styles.padding;
  } catch (error) {
    // disabled-eslint-next
    console.log("error-->", error);
  }
  console.log("drawY-->", drawY);
  // 结束
  let canvasData = ctx.getImageData(0, 0, canvas.width, drawY);
  canvas.height = drawY;
  ctx.clearRect(0, 0, canvas.width, drawY);
  ctx.putImageData(canvasData, 0, 0);
  drawSuccessEvent(options);
}

/**
 * 加载图片
 * @param {*} src
 * @returns
 */
function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();

    img.onload = () => {
      resolve(img);
    };
    img.onerror = (err) => {
      reject(err);
    };
    img.crossOrigin = "";
    img.src = src;
  });
}

/**
 * 绘制文字
 * @param {*} ctx
 * @param {*} text
 * @param {*} styles
 * @param {*} drawX
 * @param {*} drawY
 * @param {*} options
 * @returns
 */
function drawText(ctx, text, styles, drawX, drawY, options) {
  drawX = 0;
  const defaultOptions = {
    offsetX: 0,
    display: "block",
  };
  if (!options) {
    options = defaultOptions;
  } else {
    options = { ...defaultOptions, ...options };
  }
  const { offsetX, display } = options;

  const reg = /[a-zA-Z,，。？//：:"“‘”;]/;
  const textArr = text.split("\n");
  ctx.fillStyle = styles.color;
  ctx.font = `${styles.fontSize}px ${styles.fontFamily}`;
  if (display === "block") {
    drawY += styles.fontSize + styles.lineSpacing * 2;
  }
  for (let i = 0; i < textArr.length; i++) {
    if (display === "inline") {
      drawX = offsetX;
    } else {
      drawX = styles.textBoxPadding + styles.padding + offsetX;
    }
    const line = textArr[i];
    for (let j = 0; j < line.length; j++) {
      const text = line.substr(j, 1);
      if (text === " ") {
        continue;
      }
      const x = drawX;
      const y = drawY;
      console.log("drawY-->", drawY);
      ctx.fillText(text, x, y);
      // ctx.strokeStyle = "green";
      // ctx.strokeRect(
      //     drawX,
      //     y - styles.fontSize,
      //     styles.fontSize,
      //     styles.fontSize
      // );

      // 标点符号和字母的大小就除以2
      const nextText = line[j + 1];
      if (reg.test(text)) {
        drawX += styles.fontSize / 2 + styles.letterSpacing / 2;
      } else {
        if (reg.test(nextText)) {
          drawX += styles.fontSize + styles.letterSpacing / 2;
        } else {
          drawX += styles.fontSize + styles.letterSpacing;
        }
      }
      // 换行处理,判断文字的右下坐标有没有超过边界
      if (drawX + styles.fontSize > ctx.canvas.width - (styles.padding + styles.textBoxPadding) && nextText) {
        if (display === "inline") {
          drawX = offsetX;
        } else {
          drawX = styles.textBoxPadding + styles.padding + offsetX;
        }
        drawY += styles.fontSize + styles.lineSpacing;
      }
    }
    drawY += styles.fontSize + styles.lineSpacing;
  }
  return {
    drawX,
    drawY,
  };
}

/**
 * 绘制底部二维码和其他信息
 */
// eslint-disable-next-line
async function drawBottom(ctx, options, drawX, drawY) {
  try {
    const url = "https://star.top237.top/ry-api/start/qrcode?msg=" + encodePath(options.qrcodeUrl);
    const img = await loadImage(url);
    console.log("options.styles.padding-->", options.styles.padding);
    const x = options.styles.padding;
    const y = drawY;
    const width = 210;
    const height = 210;
    ctx.drawImage(img, x, y, width, height);
    drawText(ctx, "长按识别可进入网页播放", { ...options.styles, fontSize: 12 * options.scale }, 0, y + height / 2, {
      display: "inline",
      offsetX: width + x + 10,
    });
    ctx.fillText("star.top237.top", width + x + 10, y + height / 2 + 12 * options.scale + 8);
    drawY += height;
  } catch (error) {
    throw new Error("加载二维码图片错误-->", error);
  }
  return {
    drawX,
    drawY,
  };
}

export function encodePath(path) {
  // 使用encodeURI对路径进行编码
  path = encodeURI(path);
  // 替换空格为%20
  path = path.replace(/\s/g, "%20");
  // 替换#为%23
  path = path.replace(/#/g, "%23");
  // 替换?为%3F
  path = path.replace(/\?/g, "%3F");
  return path;
}

/**
 * 绘制成功后的回调函数
 * @param {*} options
 */
function drawSuccessEvent(options) {
  if (options.onSuccess && typeof options.onSuccess == "function") {
    options.onSuccess();
  }
}
